using System;
using System.Text;
using UnityEngine;

public class NetPacketTCP : NetConnTCP.IReader
{
    private int sendBufferSize = 0;
    private int readBufferSize = 0;
    private int readSize = 0;
    private int packageLength = 0;

    public static readonly int HeaderByteSize = 2;

    private byte[] sendBuffer = null;
    private NetworkStream sendStream = null;

    public delegate void OnPacket(byte[] data,int size);

    public event OnPacket onPacket;


    public NetPacketTCP(int readBufferSize,int sendBufferSize)
    {
        this.readBufferSize = readBufferSize;
        this.sendBufferSize = sendBufferSize;

        sendBuffer = new byte[sendBufferSize];
        sendStream = new NetworkStream(sendBuffer);
    }

    public void Reset()
    {
        readSize = 0;
        packageLength = 0;
    }

    public void BeginSendStream()
    {
        sendStream.Position = HeaderByteSize;
    }

    public NetworkInputStream GetSendStream()
    {
        return new NetworkInputStream(sendStream);
    }

    public void WriteToSendStream(byte[] buffer, int offset, int count)
    {
        sendStream.Write(buffer, offset, count);
    }

    public byte[] FlushSendStream(ref int retCount)
    {
        if(sendStream.Position < HeaderByteSize)
        {
            throw new Exception("position < HeaderByteSize");
        }

        retCount = (int)sendStream.Position;

        ulong packageSize = (ulong)(sendStream.Position - HeaderByteSize);

        Tools.ULongBytes(packageSize, sendBuffer, 0, HeaderByteSize, false);

        sendStream.Position = 0;

        return sendBuffer;
    }

    public byte[] PackageSendBuffer(byte[] buffer, int offset, int count,ref int retCount)
    {
        if(null == buffer || (count + offset > buffer.Length) || (count + HeaderByteSize > sendBufferSize))
        {
            Debug.LogError("PackageSendBuffer failed! offset:" + offset + " count:" + count);
            return null;
        }

        retCount = HeaderByteSize + count;

        Tools.ULongBytes((ulong)count, sendBuffer,0,HeaderByteSize,false);

        Array.Copy(buffer,offset,sendBuffer,HeaderByteSize,count);

        return sendBuffer;
    }

    public bool OnRead(byte[] buffer,int size,ref int retOffset,ref int retSize)
    {
        readSize += size;

        if(0 == packageLength)
        {
            if(readSize < HeaderByteSize)
            {
                retOffset = readSize;
                retSize = HeaderByteSize - readSize;
                return true;
            }
            else
            {
                //包头有2字节大端数字表示的包体长度字段
                packageLength = (int)Tools.Bytes2ULong(buffer,0,HeaderByteSize,false);
                readSize -= HeaderByteSize;

                if(packageLength > readBufferSize)
                {
                    return false;
                }

                if(readSize > 0)
                {
                    Tools.MoveBytes(buffer,HeaderByteSize,0,readSize);
                }
            }
        }

        if(readSize < packageLength)
        {
            retOffset = readSize;
            retSize = packageLength - readSize;
            return true;
        }
        else
        {
            readSize -= packageLength;

            try
            {
                if(onPacket != null)
                {
                    onPacket(buffer,packageLength);
                }
            }
            catch(Exception ex)
            {
                Debug.LogError("NetPacketTCP OnRead Exception:" + ex);
            }

            if(readSize > 0)
            {
                Tools.MoveBytes(buffer,packageLength,0,readSize);
            }
            packageLength = 0;
            retOffset = readSize;
            retSize = HeaderByteSize - readSize;

            return true;
        }
    }

}